#include <assert.h>
#include "Boss.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>



void initBoss (Boss* pboss, const TypeBoss type_boss, const float posX, const float posY, Trajectoire* ptraj, const int direction)
{
	assert(pboss!=NULL && posX>=0 && posY>=0 && ptraj!=NULL);
	pboss->type_ennemi_boss=type_boss;
	pboss->posX_boss = posX;
	pboss->posY_boss = posY;
	pboss->ptraj_boss = ptraj;
	pboss->timer_traj = 20;
	pboss->direction = direction;
	if(type_boss == 0)	
	{
		pboss->tailleX_boss = 6;
		pboss->tailleY_boss = 6;
		pboss->PV_boss = 100;
		
	}
	else if(type_boss == 1)	
	{
		pboss->tailleX_boss = 7;
		pboss->tailleY_boss = 7;
		pboss->PV_boss = 200;
	
	}
	else if(type_boss == 2)	
	{
		pboss->tailleX_boss = 8;
		pboss->tailleY_boss = 8;
		pboss->PV_boss = 300;
		
	}
}

Boss* creerBoss (const TypeBoss type_boss, const float posX, const float posY, Trajectoire* ptraj, const int direction)
{
	assert(posX>=0 && posY>=0 && ptraj!=NULL);
	Boss* pboss;
	pboss=(Boss*)malloc(sizeof(Boss));
	initBoss(pboss, type_boss, posX, posY, ptraj, direction);
	return(pboss);
}

void libereBoss (Boss* pboss)
{
	assert(pboss!=NULL);
	detruireTrajectoire(&(pboss->ptraj_boss));
}

void detruireBoss (Boss** ppboss)
{
	assert(ppboss!=NULL);
	libereBoss(*ppboss);
	free(*ppboss);
	*ppboss=NULL;
}

TypeBoss getTypeEnnemiBoss (const Boss* pboss)
{
	assert(pboss!=NULL);
	return (pboss->type_ennemi_boss);
}

void setTypeEnnemiBoss (Boss* pboss, const TypeBoss type_boss)
{
	assert(pboss!=NULL);
	assert(type_boss == 0 || type_boss == 1 || type_boss == 2);
	pboss->type_ennemi_boss=type_boss;
}

const int getPVBoss (const Boss* pboss)
{
	assert(pboss!=NULL);
	return (pboss->PV_boss);
}

void setPVBoss (Boss* pboss, const int PV)
{
	assert(pboss!=NULL  && PV>=0);
	pboss->PV_boss=PV;
}

const float getPosXBoss (const Boss* pboss)
{
	assert(pboss!=NULL);
	return (pboss->posX_boss);
}

void setPosXBoss (Boss* pboss, const float posX)
{
	assert(pboss!=NULL && posX>=0);
	pboss->posX_boss=posX;
}

const float getPosYBoss (const Boss* pboss)
{
	assert(pboss!=NULL);
	return (pboss->posY_boss);
}

void setPosYBoss (Boss* pboss, const float posY)
{
	assert(pboss!=NULL && posY>=0);
	pboss->posY_boss=posY;
}

const float getTailleXBoss (const Boss* pboss)
{
	assert(pboss!=NULL);
	return (pboss->tailleX_boss);
}

void setTailleXBoss (Boss* pboss, const float tailleX)
{
	assert(pboss!=NULL && tailleX>0);
	pboss->tailleX_boss=tailleX;
}

const float getTailleYBoss (const Boss* pboss)
{
	assert(pboss!=NULL);
	return (pboss->tailleY_boss);
}

void setTailleYBoss (Boss* pboss, const float tailleY)
{
	assert(pboss!=NULL && tailleY>0);
	pboss->tailleY_boss=tailleY;
}

const int getTimerTrajBoss (const Boss* pboss)
{
	assert (pboss!=NULL);
	return (pboss->timer_traj);
}

void setTimerTrajBoss (Boss* pboss, const int timertraj)
{
	assert (pboss!=NULL && timertraj>=0);
	pboss->timer_traj=timertraj;
}

const int terEstPositionBossValide (const Terrain* pterrain,Boss* pboss, const float deplacementX,
	     const float deplacementY)
{
	assert (pterrain!=NULL && pboss!=NULL);
	if ((getPosXBoss(pboss)+getTailleXBoss(pboss)+deplacementX<=getDimX_terrain(pterrain))
		&&(getPosYBoss(pboss)+getTailleYBoss(pboss)+deplacementY<=getDimY_terrain(pterrain))
		&&(getPosXBoss(pboss)+deplacementX>=0)
		&& (getPosYBoss(pboss)+deplacementY>=0))
		return 0;
	return 1;
}


void deplacerBoss (Boss* pboss, Terrain* pterrain)
{
	assert(pboss->direction == 0 || pboss->direction == 1);
	if (pboss!=NULL && pterrain!=NULL);
	{
		float t = pboss->ptraj_boss->vitesse1;
		float deplacementX = t*(pboss->ptraj_boss->vectx);
		float deplacementY = t*(pboss->ptraj_boss->vecty);
		if (getPosXBoss(pboss) < pboss->ptraj_boss->ppoint2->posX_point && pboss->direction == 0)  // le boss va à droite.
		{
			
			setPosXBoss(pboss, getPosXBoss(pboss)+deplacementX);
			setPosYBoss(pboss, getPosYBoss(pboss)+deplacementY);
			if (getPosXBoss(pboss) == pboss->ptraj_boss->ppoint2->posX_point-1)
				pboss->direction = 1; // le boss change de direction juste avant de finir son déplacement.
		}
		else if (getPosXBoss(pboss) > pboss->ptraj_boss->ppoint1->posX_point && pboss->direction == 1) // le boss va à gauche.
		{
			setPosXBoss(pboss, getPosXBoss(pboss)-deplacementX);
			setPosYBoss(pboss, getPosYBoss(pboss)-deplacementY);
			if (getPosXBoss(pboss) == pboss->ptraj_boss->ppoint1->posX_point+1)
				pboss->direction = 0;
		}	
		
	}
}


Tir* tirerBoss (Boss* pboss, Terrain* pterrain, Heros* pheros)
{
	assert(pboss!=NULL && pterrain!=NULL && pheros!=NULL);
	int i;
	srand(time(NULL));
	if(getTypeEnnemiBoss(pboss) == 1)
	{
		i= (int)rand()%10; // Vitesses différentes de tir.
		if (i < 2)
		{
		Point* pt1 = creerPoint(getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss));
		Point* pt2 = creerPoint(getPosXHeros(pheros)+0.5*getTailleXHeros(pheros),getPosYHeros(pheros));
		Trajectoire* ptraj = creerTrajectoire(pt1, pt2, 0.6);
		Tir* ptir = creerTir(1, 1, getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss), ptraj, 1); 
		return ptir;
		}
		else if ( i>=2 && i<4)
		{
		Point* pt1 = creerPoint(getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss));
		Point* pt2 = creerPoint(getPosXHeros(pheros)+0.5*getTailleXHeros(pheros),getPosYHeros(pheros));
		Trajectoire* ptraj = creerTrajectoire(pt1, pt2, 0.4);
		Tir* ptir = creerTir(1, 1, getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss), ptraj, 1); 
		return ptir;
		}
		else if ( i>=4 && i<6)
		{
		Point* pt1 = creerPoint(getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss));
		Point* pt2 = creerPoint(50, getPosYHeros(pheros));
		Trajectoire* ptraj = creerTrajectoire(pt1, pt2, 0.3);
		Tir* ptir = creerTir(1, 1, getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss), ptraj, 1); 
		return ptir;
		}
	}
	else
	{
		i= (int)rand()%3; // Vitesses différentes de tir.
		if (i < 1)
		{
		Point* pt1 = creerPoint(getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss));
		Point* pt2 = creerPoint(getPosXHeros(pheros)+0.5*getTailleXHeros(pheros),getPosYHeros(pheros));
		Trajectoire* ptraj = creerTrajectoire(pt1, pt2, 1.2);
		Tir* ptir = creerTir(1, 1, getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss), ptraj, 1); 
		return ptir;
		}
	}
	//Pas de tir.
		{
		Point* pt1 = creerPoint(getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss));
		Point* pt2 = creerPoint(getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss));
		Trajectoire* ptraj = creerTrajectoire(pt1, pt2, 0.1);
		Tir* ptir = creerTir(1, 1, getPosXBoss(pboss)+0.5*getTailleXBoss(pboss), getPosYBoss(pboss)+getTailleYBoss(pboss)+2, ptraj, 1); 
		return ptir;
		}
		
}

void enleverVieBoss (Boss* pboss, const int degat)
{
	assert(pboss!=NULL && degat > 0);
	if (getPVBoss(pboss) > degat)
		setPVBoss(pboss, (pboss->PV_boss)-degat);
	else
		setPVBoss(pboss, 0);
}


/** @brief Cette procedure permet de tester toutes les fonctions du module*/
void testRegressionBoss ()
{
	printf ("on va declarer un Boss\n\n");	
	Boss* pmechant;
	printf ("on va declarer une trajectoire\n\n");	
	Trajectoire* ptraj;
	int pv;
	float tailleX;
	printf ("on va declarer des points\n\n");	
	Point* ppt1;
	Point* ppt2;
	printf ("on va creer des points\n\n");
	ppt1=creerPoint (1, 2);
	ppt2=creerPoint (2, 3);
	printf ("on va creer une trajectoire\n\n");
	ptraj=creerTrajectoire (ppt1, ppt2, 2.00);
	printf ("Creation de Boss ouais gros\n");
	pmechant=creerBoss (2, 5, 10, ptraj, 0);
	printf("Creation reussie\n");
	printf("La position X de Boss est censee etre 5\n");
	printf("En realite, posX = %f\n", getPosXBoss(pmechant));
	printf ("type: %d, pv: %d, posX: %f, posY: %f, tailleX: %f, tailleY: %f\n",
			getTypeEnnemiBoss(pmechant), getPVBoss(pmechant), getPosXBoss(pmechant),
			getPosYBoss(pmechant), getTailleXBoss(pmechant), getTailleYBoss(pmechant));
	printf("On change ses PV à 500\n");
	setPVBoss(pmechant, 500);
	pv=getPVBoss(pmechant);
	if (pv!=500)
		printf("Erreur getPv\n");
	else
		printf("getPv reussi\n");
	printf("On change sa tailleX à 1000\n");
	setTailleXBoss(pmechant, 1000);
	tailleX=getTailleXBoss(pmechant);
	if (tailleX!=1000)
		printf("Erreur get/setTx\n");
	else
		printf("get/setTx reussi\n");
	enleverVieBoss(pmechant, 1);
	printf("Boss a perdu 1 de vie\n");
	printf ("type: %d, pv: %d, posX: %f, posY: %f, tailleX: %f, tailleY: %f\n",
			getTypeEnnemiBoss(pmechant), getPVBoss(pmechant), getPosXBoss(pmechant),
			getPosYBoss(pmechant), getTailleXBoss(pmechant), getTailleYBoss(pmechant));
	
	detruireBoss(&pmechant);
	printf("Apres destruction l'adresse devrait etre nulle, elle est %p\n\n",pmechant);
	
	printf ("fin du test du module Boss\n\n");
}
